/**
 * $Revision$
 * $Date$
 *
 * Copyright (C) https://gitee.com/baibaiclouds/platform . All rights reserved.
 * <p>
 * This software is the confidential and proprietary information of .
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the agreements you entered into with .
 * 
 * Modified history:
 *   baibai  2021年4月16日 下午11:25:31  created
 */
package com.desktop.web.service.websession;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.desktop.web.core.exception.BusinessException;
import com.desktop.web.core.utils.DateUtil;
import com.desktop.web.core.utils.TaskEngine;
import com.desktop.web.core.utils.Util;
import com.desktop.web.service.remotecpe.NatInfo;
import com.desktop.web.service.remotecpe.RemotecpeService;
import com.desktop.web.service.user.UserService;
import com.desktop.web.uda.entity.User;

/**
 * 
 *
 * @author baibai
 */
@Service
public class WebSessionService implements InitializingBean {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public static WebSessionService webSessionService;

    @Value("${websession.timeout.max.sec}")
    private Integer WEBSESSION_TIMEOUT_MAX;

    @Value("${websession.timeout.interval.sec}")
    private Integer WEBSESSION_TIMEOUT_INTERVAL;

    @Autowired
    private UserService userService;

    @Autowired
    private RemotecpeService remotecpeService;

    private Map<Long, WebSession> sessions = new ConcurrentHashMap<Long, WebSession>();
    private Map<String, Long> tokenToUid = new ConcurrentHashMap<String, Long>();

    @Override
    public void afterPropertiesSet() throws Exception {
        WebSessionService.webSessionService = this;

        TaskEngine.getInstance().schedule(new TimerTask() {
            @Override
            public void run() {
                checkTimeout();
            }
        }, 1000, WEBSESSION_TIMEOUT_INTERVAL * 1000);
    }

    /**
     * 检测websession是否超时
     */
    private void checkTimeout() {
        Long cuttiem = DateUtil.getCurtime();
        int maxtime = WEBSESSION_TIMEOUT_MAX * 1000;
        List<Long> delkey = new ArrayList<Long>();
        sessions.forEach((uid, session) -> {
            if (cuttiem - session.getLastTime().getTime() < maxtime) {
                return;
            }
            delkey.add(uid);
        });

        for (Long uid : delkey) {
            this.deleteWebSession(uid);
            logger.info("user web session timeout,now del,uid:{}", uid);
        }
    }

    /**
     * 创建web会话
     * 
     * @param uid
     * @return
     */
    public WebSession makeWebSession(User user) {
        WebSession session = sessions.get(user.getId());

        if (session == null) {
            session = new WebSession(user.getId(), user.getUsername(), Util.UUID());
            sessions.put(user.getId(), session);
            tokenToUid.put(session.getToken(), session.getUid());
        }

        session.setLastTime(new Date());
        logger.info("user make web session success,uid:{},token:{}", user.getId(), session.getToken());
        return session;
    }

    /**
     * 删除websession
     * 
     * @param uid
     */
    public void deleteWebSession(Long uid) {
        WebSession webSession = sessions.get(uid);
        if (webSession == null) {
            return;
        }

        sessions.remove(uid);
        tokenToUid.remove(webSession.getToken());
        logger.info("del user web session success,uid:{},token:{}", uid, webSession.getToken());
    }

    /**
     * web登录
     * 
     * @param username
     * @param password
     */
    public WebSession webLogin(String username, String password) {
        User user = userService.getUserByUsername(username);
        if (user == null) {
            throw new BusinessException("登录账号或密码错误");
        }

        if (!user.getPassword().equals(password)) {
            throw new BusinessException("登录账号或密码错误");
        }

        WebSession webSession = this.makeWebSession(user);
        logger.info("user web login success,username:{}", username);
        return webSession;
    }

    /**
     * 根据token获取会话信息
     * 
     * @param token
     * @return
     */
    public WebSession getWebSessionByToken(String token) {

        if (StringUtils.isEmpty(token)) {
            return null;
        }

        Long uid = tokenToUid.get(token);
        if (uid == null) {
            return null;
        }

        return sessions.get(uid);
    }

    /**
     * 刷新token
     * 
     * @param token
     */
    public WebSession refreshToken(String token) {
        try {

            WebSession webSession = this.getWebSessionByToken(token);
            if (webSession == null) {
                return null;
            }

            webSession.setLastTime(new Date());
            return webSession;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    public NatInfo refreshUUID(String uuid) {
        return remotecpeService.ping(uuid);
    }

    /**
     * 退出登录
     * 
     * @param uid
     */
    public void logout(Long uid) {
        this.deleteWebSession(uid);
    }

}
